import os
import sys
import sqlite3
import shutil
import threading
import datetime
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.checkbox import CheckBox
from kivy.uix.filechooser import FileChooserListView
from kivy.uix.popup import Popup
from kivy.uix.recycleview import RecycleView
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.properties import StringProperty, ListProperty, BooleanProperty, ObjectProperty
from kivy.uix.togglebutton import ToggleButton
from kivy.clock import Clock
from kivy.core.text import LabelBase
from kivy.config import Config
from kivy.lang import Builder

# 设置窗口大小为典型手机屏幕尺寸
Config.set('graphics', 'width', '360')
Config.set('graphics', 'height', '640')
Config.set('graphics', 'resizable', False)

# 尝试加载中文字体支持
if sys.platform == 'android':
    # 在Android上，字体应该在应用资源中
    pass

class ScanThread(threading.Thread):
    """文件扫描线程"""
    def __init__(self, root_paths, extensions=None, callback=None):
        super().__init__()
        self.root_paths = root_paths
        self.extensions = extensions if extensions is not None else []
        self.running = True
        self.found_files = []
        self.callback = callback
        self.total_files = 0
    
    def run(self):
        for root_path in self.root_paths:
            if not self.running:
                break
                
            for dirpath, _, filenames in os.walk(root_path):
                if not self.running:
                    break
                    
                for filename in filenames:
                    if not self.running:
                        break
                        
                    # 检查文件扩展名是否在指定的列表中
                    if any(filename.lower().endswith(ext.lower()) for ext in self.extensions):
                        try:
                            full_path = os.path.join(dirpath, filename)
                            file_size = os.path.getsize(full_path)
                            # 获取文件创建时间
                            creation_time = os.path.getctime(full_path)
                            # 格式化为可读时间
                            formatted_time = datetime.datetime.fromtimestamp(creation_time).strftime('%Y-%m-%d %H:%M:%S')
                            
                            file_info = {
                                'name': filename,
                                'path': full_path,
                                'size': self.format_size(file_size),
                                'ext': filename.split('.')[-1].upper(),
                                'created': formatted_time
                            }
                            self.found_files.append(file_info)
                            # 回调处理找到的文件
                            if self.callback:
                                Clock.schedule_once(lambda dt, info=file_info: self.callback(info), 0)
                        except Exception as e:
                            continue
                            
                    self.total_files += 1
                    if self.total_files % 100 == 0:
                        # 更新进度
                        if self.callback:
                            Clock.schedule_once(lambda dt: self.callback({'progress': self.total_files}), 0)
        
        # 扫描完成
        if self.callback and self.running:
            Clock.schedule_once(lambda dt: self.callback({'finished': True}), 0)
    
    def stop(self):
        self.running = False
    
    @staticmethod
    def format_size(size_bytes):
        """格式化文件大小为人类可读形式"""
        for unit in ['B', 'KB', 'MB', 'GB']:
            if size_bytes < 1024.0:
                return f"{size_bytes:.2f} {unit}"
            size_bytes /= 1024.0
        return f"{size_bytes:.2f} TB"

class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior, RecycleGridLayout):
    """支持选择的RecycleView布局"""
    pass

class SelectableLabel(RecycleDataViewBehavior, BoxLayout):
    """可选择的标签组件"""
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)
    file_info = ObjectProperty(None)
    
    def refresh_view_attrs(self, rv, index, data):
        """刷新视图属性"""
        self.index = index
        self.file_info = data
        return super().refresh_view_attrs(rv, index, data)
    
    def on_touch_down(self, touch):
        """处理触摸事件"""
        if super().on_touch_down(touch):
            return True
        if self.collide_point(*touch.pos) and self.selectable:
            return self.parent.select_with_touch(self.index, touch)
    
    def apply_selection(self, rv, index, is_selected):
        """应用选择状态"""
        self.selected = is_selected
        if is_selected:
            rv.selected_item = self.file_info

class FileItem(BoxLayout):
    """文件列表项组件"""
    name = StringProperty("")
    size = StringProperty("")
    date = StringProperty("")
    ext = StringProperty("")

class FileTypeToggle(BoxLayout):
    """文件类型选择器"""
    text = StringProperty("")
    group = StringProperty("")
    state = BooleanProperty(False)

class FileActionPopup(Popup):
    """文件操作弹出菜单"""
    file_info = ObjectProperty(None)
    app = ObjectProperty(None)
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.size_hint = (0.8, 0.6)

class SQLiteManager:
    """SQLite数据库管理类"""
    def __init__(self):
        # 在Android上，使用应用私有存储目录
        if sys.platform == 'android':
            from android import mActivity
            from jnius import autoclass
            
            Context = autoclass('android.content.Context')
            self.db_path = os.path.join(
                mActivity.getExternalFilesDir(None).getAbsolutePath(),
                'file_notes.db'
            )
        else:
            self.db_path = 'file_notes.db'
        self.init_db()
    
    def init_db(self):
        """初始化数据库"""
        try:
            conn = sqlite3.connect(self.db_path)
            c = conn.cursor()
            c.execute('''CREATE TABLE IF NOT EXISTS file_notes
                         (path TEXT PRIMARY KEY, note TEXT)''')
            conn.commit()
            conn.close()
        except Exception as e:
            print(f"初始化数据库失败: {str(e)}")
    
    def get_note(self, file_path):
        """从数据库获取备注"""
        try:
            conn = sqlite3.connect(self.db_path)
            c = conn.cursor()
            c.execute("SELECT note FROM file_notes WHERE path=?", (file_path,))
            result = c.fetchone()
            conn.close()
            return result[0] if result else ""
        except Exception as e:
            print(f"获取备注失败: {str(e)}")
            return ""
    
    def save_note(self, file_path, note):
        """保存备注到数据库"""
        try:
            conn = sqlite3.connect(self.db_path)
            c = conn.cursor()
            c.execute("REPLACE INTO file_notes (path, note) VALUES (?, ?)", 
                     (file_path, note))
            conn.commit()
            conn.close()
            return True
        except Exception as e:
            print(f"保存备注失败: {str(e)}")
            return False

class MobileScannerApp(App):
    """Android移动版文件扫描应用"""
    title = '文件扫描工具'
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.scan_thread = None
        self.files = []
        self.filtered_files = []
        self.selected_extensions = []
        self.db_manager = SQLiteManager()
        self.current_directory = None
        
        # 文件类型定义
        self.file_types = {
            # 文档类型
            '.ppt': 'PPT',
            '.pptx': 'PPTX',
            '.doc': 'DOC',
            '.docx': 'DOCX',
            '.pdf': 'PDF',
            '.xls': 'XLS',
            '.xlsx': 'XLSX',
            # 代码文件类型
            '.py': 'Python',
            # 图片类型
            '.jpg': 'JPG',
            '.jpeg': 'JPEG',
            '.png': 'PNG',
            '.gif': 'GIF',
            '.bmp': 'BMP',
            # 视频类型
            '.mp4': 'MP4',
            '.avi': 'AVI',
            '.mov': 'MOV',
            '.wmv': 'WMV'
        }
    
    def build(self):
        """构建应用界面"""
        # 主布局
        main_layout = BoxLayout(orientation='vertical', padding=10, spacing=10)
        
        # 顶部控制区域
        control_layout = BoxLayout(orientation='vertical', spacing=10)
        
        # 路径选择
        path_layout = BoxLayout(orientation='horizontal', spacing=5)
        self.path_input = TextInput(text="/storage/emulated/0/Download", multiline=False, hint_text="扫描目录")
        path_layout.add_widget(self.path_input)
        browse_btn = Button(text="浏览", size_hint_x=0.3)
        browse_btn.bind(on_press=self.browse_directory)
        path_layout.add_widget(browse_btn)
        control_layout.add_widget(path_layout)
        
        # 文件类型选择（可滚动）
        type_scroll = ScrollView(size_hint=(1, 0.2))
        type_grid = GridLayout(cols=3, spacing=5, size_hint_y=None)
        type_grid.bind(minimum_height=type_grid.setter('height'))
        
        self.checkboxes = {}
        for ext, name in self.file_types.items():
            type_item = BoxLayout(orientation='vertical', size_hint_y=None, height=60)
            checkbox = CheckBox(group='file_type')
            label = Label(text=name, font_size='12sp')
            type_item.add_widget(checkbox)
            type_item.add_widget(label)
            type_grid.add_widget(type_item)
            self.checkboxes[ext] = checkbox
            checkbox.bind(active=lambda instance, value, e=ext: self.on_checkbox_change(instance, value, e))
        
        type_scroll.add_widget(type_grid)
        control_layout.add_widget(type_scroll)
        
        # 扫描控制按钮
        scan_buttons = BoxLayout(orientation='horizontal', spacing=5)
        self.scan_btn = Button(text="开始扫描", background_color=(0, 0.7, 0, 1))
        self.scan_btn.bind(on_press=self.start_scan)
        scan_buttons.add_widget(self.scan_btn)
        
        self.stop_btn = Button(text="停止扫描", background_color=(0.7, 0, 0, 1), disabled=True)
        self.stop_btn.bind(on_press=self.stop_scan)
        scan_buttons.add_widget(self.stop_btn)
        
        control_layout.add_widget(scan_buttons)
        
        # 搜索框和搜索模式
        search_layout = BoxLayout(orientation='horizontal', spacing=5)
        self.search_input = TextInput(hint_text="搜索", multiline=False)
        self.search_mode = Spinner(
            text='任意字符',
            values=['任意字符', '备注搜索'],
            size_hint_x=0.3
        )
        self.search_input.bind(text=self.on_search_text_change)
        search_layout.add_widget(self.search_input)
        search_layout.add_widget(self.search_mode)
        control_layout.add_widget(search_layout)
        
        main_layout.add_widget(control_layout)
        
        # 文件列表
        self.file_list = RecycleView()
        self.file_list.layout_manager = SelectableRecycleGridLayout(
            cols=1, spacing=5, default_size=(None, 70), default_size_hint=(1, None),
            size_hint_y=None, multiselect=False
        )
        self.file_list.data = []
        self.file_list.viewclass = 'FileItem'
        self.file_list.layout_manager.bind(selected_nodes=self.on_file_selected)
        main_layout.add_widget(self.file_list)
        
        # 状态栏
        status_layout = BoxLayout(orientation='vertical', size_hint=(1, 0.1))
        self.status_label = Label(text="就绪", halign='left', valign='middle', font_size='12sp')
        self.count_label = Label(text="找到: 0 个文件", halign='left', valign='middle', font_size='12sp')
        status_layout.add_widget(self.status_label)
        status_layout.add_widget(self.count_label)
        main_layout.add_widget(status_layout)
        
        # 操作弹出菜单
        self.action_popup = FileActionPopup(title="文件操作", size_hint=(0.8, 0.6))
        self.action_popup.app = self
        
        return main_layout
    
    def browse_directory(self, instance):
        """浏览选择目录"""
        # 在Android上，我们使用FileChooser
        popup = Popup(title="选择目录", size_hint=(0.9, 0.8))
        
        file_chooser = FileChooserListView(path="/storage/emulated/0", dirselect=True)
        
        button_layout = BoxLayout(orientation='horizontal', spacing=5, size_hint=(1, 0.1))
        select_btn = Button(text="选择")
        cancel_btn = Button(text="取消")
        
        def on_select(instance):
            if file_chooser.selection:
                self.path_input.text = file_chooser.selection[0]
            popup.dismiss()
        
        def on_cancel(instance):
            popup.dismiss()
        
        select_btn.bind(on_press=on_select)
        cancel_btn.bind(on_press=on_cancel)
        
        button_layout.add_widget(select_btn)
        button_layout.add_widget(cancel_btn)
        
        popup_layout = BoxLayout(orientation='vertical')
        popup_layout.add_widget(file_chooser)
        popup_layout.add_widget(button_layout)
        
        popup.content = popup_layout
        popup.open()
    
    def on_checkbox_change(self, instance, value, ext):
        """处理复选框变化"""
        if value and ext not in self.selected_extensions:
            self.selected_extensions.append(ext)
        elif not value and ext in self.selected_extensions:
            self.selected_extensions.remove(ext)
    
    def on_search_text_change(self, instance, value):
        """搜索文本变化"""
        self.filter_files(value)
    
    def start_scan(self, instance):
        """开始扫描"""
        path = self.path_input.text
        if not path or not os.path.isdir(path):
            self.show_message("错误", "请选择有效的扫描目录")
            return
    
        # 检查是否选择了文件类型
        if not self.selected_extensions:
            self.show_message("提示", "请至少选择一种文件类型进行扫描")
            return
    
        # 清空文件列表
        self.files = []
        self.filtered_files = []
        self.file_list.data = []
        self.count_label.text = "找到: 0 个文件"
    
        # 启动扫描线程
        self.scan_thread = ScanThread([path], self.selected_extensions, self.on_file_found)
        
        # 更新UI状态
        self.scan_btn.disabled = True
        self.stop_btn.disabled = False
        
        # 显示扫描状态
        type_names = [self.file_types.get(ext, ext) for ext in self.selected_extensions]
        self.status_label.text = f"正在扫描{"、".join(type_names)}文件..."
        
        self.scan_thread.start()
    
    def stop_scan(self, instance):
        """停止扫描"""
        if self.scan_thread and self.scan_thread.is_alive():
            self.scan_thread.stop()
            self.status_label.text = "正在停止扫描..."
    
    def on_file_found(self, data):
        """处理找到的文件"""
        if 'progress' in data:
            # 更新进度
            pass
        elif 'finished' in data:
            # 扫描完成
            self.scan_btn.disabled = False
            self.stop_btn.disabled = True
            count = len(self.filtered_files)
            self.status_label.text = f"扫描完成，共找到 {count} 个文件"
        else:
            # 找到新文件
            self.files.append(data)
            # 自动过滤
            search_text = self.search_input.text
            if search_text:
                self.filter_files(search_text)
            else:
                self.filtered_files.append(data)
                self.add_file_to_list(data)
    
    def add_file_to_list(self, file_info):
        """添加文件到列表"""
        self.file_list.data.append({
            'name': file_info['name'],
            'ext': file_info['ext'],
            'size': file_info['size'],
            'date': file_info['created'][:10],
            'file_info': file_info
        })
        # 更新计数
        self.count_label.text = f"找到: {len(self.filtered_files)} 个文件"
    
    def filter_files(self, search_text):
        """过滤文件列表，支持在文件名和备注中搜索"""
        if not search_text.strip():
            self.filtered_files = self.files.copy()
            self.file_list.data = [
                {
                    'name': f['name'],
                    'ext': f['ext'],
                    'size': f['size'],
                    'date': f['created'][:10],
                    'file_info': f
                } for f in self.files
            ]
        else:
            search_lower = search_text.lower()
            search_mode = self.search_mode.text
            
            self.filtered_files = []
            for f in self.files:
                file_path = f['path']
                # 获取文件备注
                note = self.db_manager.get_note(file_path)
                
                if search_mode == '任意字符':
                    # 同时搜索文件名和备注
                    if search_lower in f['name'].lower() or search_lower in note.lower():
                        self.filtered_files.append(f)
                elif search_mode == '备注搜索':
                    # 只在备注中搜索
                    if search_lower in note.lower():
                        self.filtered_files.append(f)
            
            self.file_list.data = [
                {
                    'name': f['name'],
                    'ext': f['ext'],
                    'size': f['size'],
                    'date': f['created'][:10],
                    'file_info': f
                } for f in self.filtered_files
            ]
        
        # 更新计数
        self.count_label.text = f"找到: {len(self.filtered_files)} 个文件"
    
    def on_file_selected(self, instance, value):
        """处理文件选择事件"""
        if value:
            index = value[0]
            if 0 <= index < len(self.filtered_files):
                file_info = self.filtered_files[index]
                # 显示操作菜单
                self.action_popup.file_info = file_info
                self.action_popup.open()
    
    def show_message(self, title, message):
        """显示消息弹出框"""
        popup = Popup(title=title, content=Label(text=message), size_hint=(0.7, 0.4))
        popup.open()
    
    def open_file(self, file_info):
        """打开文件"""
        try:
            if sys.platform == 'android':
                # 在Android上使用Intent打开文件
                from android import mActivity
                from jnius import autoclass
                
                File = autoclass('java.io.File')
                Intent = autoclass('android.content.Intent')
                Uri = autoclass('android.net.Uri')
                FileProvider = autoclass('androidx.core.content.FileProvider')
                
                file = File(file_info['path'])
                uri = FileProvider.getUriForFile(
                    mActivity, 
                    'org.example.fileviewer.fileprovider', 
                    file
                )
                
                intent = Intent(Intent.ACTION_VIEW)
                intent.setDataAndType(uri, self.get_mime_type(file_info['path']))
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                mActivity.startActivity(intent)
            else:
                # 在其他平台上使用默认方式打开
                if os.name == 'nt':
                    os.startfile(file_info['path'])
                else:
                    import subprocess
                    subprocess.Popen(['xdg-open', file_info['path']])
            
            self.status_label.text = "文件已打开"
        except Exception as e:
            self.show_message("错误", f"无法打开文件: {str(e)}")
    
    def get_mime_type(self, file_path):
        """获取文件的MIME类型"""
        mime_types = {
            '.ppt': 'application/vnd.ms-powerpoint',
            '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            '.doc': 'application/msword',
            '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            '.pdf': 'application/pdf',
            '.xls': 'application/vnd.ms-excel',
            '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            '.py': 'text/plain',
            '.jpg': 'image/jpeg',
            '.jpeg': 'image/jpeg',
            '.png': 'image/png',
            '.gif': 'image/gif',
            '.bmp': 'image/bmp',
            '.mp4': 'video/mp4',
            '.avi': 'video/x-msvideo',
            '.mov': 'video/quicktime',
            '.wmv': 'video/x-ms-wmv'
        }
        
        ext = os.path.splitext(file_path)[1].lower()
        return mime_types.get(ext, 'application/octet-stream')
    
    def open_file_location(self, file_info):
        """打开文件所在目录"""
        try:
            directory = os.path.dirname(file_info['path'])
            
            if sys.platform == 'android':
                # 在Android上使用Intent打开目录
                from android import mActivity
                from jnius import autoclass
                
                File = autoclass('java.io.File')
                Intent = autoclass('android.content.Intent')
                Uri = autoclass('android.net.Uri')
                
                file = File(directory)
                uri = Uri.fromFile(file)
                
                intent = Intent(Intent.ACTION_VIEW)
                intent.setData(uri)
                mActivity.startActivity(intent)
            else:
                # 在其他平台上使用默认方式打开
                if os.name == 'nt':
                    os.startfile(directory)
                else:
                    import subprocess
                    subprocess.Popen(['xdg-open', directory])
        except Exception as e:
            self.show_message("错误", f"无法打开文件位置: {str(e)}")
    
    def copy_file_path(self, file_info):
        """复制文件路径"""
        try:
            if sys.platform == 'android':
                # 在Android上复制到剪贴板
                from android import mActivity
                from jnius import autoclass
                
                ClipboardManager = autoclass('android.content.ClipboardManager')
                ClipData = autoclass('android.content.ClipData')
                ClipDataItem = autoclass('android.content.ClipData$Item')
                
                clipboard = mActivity.getSystemService(mActivity.CLIPBOARD_SERVICE)
                clip = ClipData.newPlainText("文件路径", file_info['path'])
                clipboard.setPrimaryClip(clip)
            else:
                # 在其他平台上复制到剪贴板
                if os.name == 'nt':
                    import win32clipboard
                    win32clipboard.OpenClipboard()
                    win32clipboard.EmptyClipboard()
                    win32clipboard.SetClipboardText(file_info['path'])
                    win32clipboard.CloseClipboard()
                else:
                    import subprocess
                    subprocess.Popen(['xclip', '-selection', 'c'], stdin=subprocess.PIPE).communicate(file_info['path'].encode())
            
            self.status_label.text = "文件路径已复制"
        except Exception as e:
            self.show_message("提示", f"文件路径: {file_info['path']}")
    
    def add_note(self, file_info):
        """添加或编辑备注"""
        note = self.db_manager.get_note(file_info['path'])
        
        popup = Popup(title="添加备注", size_hint=(0.8, 0.6))
        
        layout = BoxLayout(orientation='vertical', padding=10, spacing=10)
        
        filename_label = Label(text=f"文件: {file_info['name']}", halign='left', valign='middle')
        layout.add_widget(filename_label)
        
        note_input = TextInput(text=note, multiline=True, hint_text="请输入备注内容...")
        layout.add_widget(note_input)
        
        button_layout = BoxLayout(orientation='horizontal', spacing=10)
        save_btn = Button(text="保存")
        cancel_btn = Button(text="取消")
        
        def on_save(instance):
            new_note = note_input.text.strip()
            if self.db_manager.save_note(file_info['path'], new_note):
                self.status_label.text = "备注已保存"
                popup.dismiss()
            else:
                self.show_message("错误", "保存备注失败")
        
        def on_cancel(instance):
            popup.dismiss()
        
        save_btn.bind(on_press=on_save)
        cancel_btn.bind(on_press=on_cancel)
        
        button_layout.add_widget(save_btn)
        button_layout.add_widget(cancel_btn)
        
        layout.add_widget(button_layout)
        
        popup.content = layout
        popup.open()
    
    def copy_to_custom_folder(self, file_info):
        """复制文件到自定义文件夹"""
        # 在Android上，我们使用FileChooser
        popup = Popup(title="选择目标文件夹", size_hint=(0.9, 0.8))
        
        file_chooser = FileChooserListView(path="/storage/emulated/0", dirselect=True)
        
        button_layout = BoxLayout(orientation='horizontal', spacing=5, size_hint=(1, 0.1))
        select_btn = Button(text="选择")
        cancel_btn = Button(text="取消")
        
        def on_select(instance):
            if file_chooser.selection:
                dest_folder = file_chooser.selection[0]
                try:
                    source_path = file_info['path']
                    dest_path = os.path.join(dest_folder, file_info['name'])
                    
                    # 如果文件已存在，询问是否覆盖
                    if os.path.exists(dest_path):
                        confirm_popup = Popup(title="文件已存在", size_hint=(0.7, 0.4))
                        confirm_layout = BoxLayout(orientation='vertical', padding=10, spacing=10)
                        confirm_layout.add_widget(Label(text=f"文件 '{file_info['name']}' 已存在。是否覆盖？"))
                        confirm_buttons = BoxLayout(orientation='horizontal', spacing=10)
                        
                        def on_yes(instance):
                            shutil.copy2(source_path, dest_path)
                            self.show_message("成功", "文件已成功复制到目标文件夹")
                            confirm_popup.dismiss()
                            popup.dismiss()
                        
                        def on_no(instance):
                            confirm_popup.dismiss()
                        
                        yes_btn = Button(text="是")
                        no_btn = Button(text="否")
                        yes_btn.bind(on_press=on_yes)
                        no_btn.bind(on_press=on_no)
                        confirm_buttons.add_widget(yes_btn)
                        confirm_buttons.add_widget(no_btn)
                        confirm_layout.add_widget(confirm_buttons)
                        confirm_popup.content = confirm_layout
                        confirm_popup.open()
                    else:
                        shutil.copy2(source_path, dest_path)
                        self.show_message("成功", "文件已成功复制到目标文件夹")
                        popup.dismiss()
                except Exception as e:
                    self.show_message("错误", f"无法复制文件: {str(e)}")
            else:
                popup.dismiss()
        
        def on_cancel(instance):
            popup.dismiss()
        
        select_btn.bind(on_press=on_select)
        cancel_btn.bind(on_press=on_cancel)
        
        button_layout.add_widget(select_btn)
        button_layout.add_widget(cancel_btn)
        
        popup_layout = BoxLayout(orientation='vertical')
        popup_layout.add_widget(file_chooser)
        popup_layout.add_widget(button_layout)
        
        popup.content = popup_layout
        popup.open()
    
    def rename_file(self, file_info):
        """重命名文件"""
        popup = Popup(title="文件重命名", size_hint=(0.8, 0.4))
        
        layout = BoxLayout(orientation='vertical', padding=10, spacing=10)
        
        filename_input = TextInput(text=file_info['name'], multiline=False, hint_text="请输入新文件名（包含扩展名）")
        layout.add_widget(filename_input)
        
        button_layout = BoxLayout(orientation='horizontal', spacing=10)
        ok_btn = Button(text="确定")
        cancel_btn = Button(text="取消")
        
        def on_ok(instance):
            new_name = filename_input.text.strip()
            if not new_name:
                return
            
            if new_name == file_info['name']:
                popup.dismiss()
                return
            
            try:
                file_path = file_info['path']
                directory = os.path.dirname(file_path)
                new_file_path = os.path.join(directory, new_name)
                
                if os.path.exists(new_file_path):
                    self.show_message("错误", f"文件名 '{new_name}' 已存在！")
                    return
                
                os.rename(file_path, new_file_path)
                
                # 更新文件信息
                file_info['name'] = new_name
                file_info['path'] = new_file_path
                
                # 刷新列表
                search_text = self.search_input.text
                self.filter_files(search_text)
                
                self.status_label.text = f"文件已重命名为 '{new_name}'"
                popup.dismiss()
            except Exception as e:
                self.show_message("错误", f"无法重命名文件: {str(e)}")
        
        def on_cancel(instance):
            popup.dismiss()
        
        ok_btn.bind(on_press=on_ok)
        cancel_btn.bind(on_press=on_cancel)
        
        button_layout.add_widget(ok_btn)
        button_layout.add_widget(cancel_btn)
        
        layout.add_widget(button_layout)
        
        popup.content = layout
        popup.open()
    
    def delete_file(self, file_info):
        """删除文件"""
        confirm_popup = Popup(title="确认删除", size_hint=(0.7, 0.4))
        
        layout = BoxLayout(orientation='vertical', padding=10, spacing=10)
        layout.add_widget(Label(text=f"确定要删除文件 '{file_info['name']}' 吗？此操作不可撤销。"))
        
        button_layout = BoxLayout(orientation='horizontal', spacing=10)
        yes_btn = Button(text="是", background_color=(0.7, 0, 0, 1))
        no_btn = Button(text="否")
        
        def on_yes(instance):
            try:
                os.remove(file_info['path'])
                
                # 从列表中移除
                if file_info in self.files:
                    self.files.remove(file_info)
                if file_info in self.filtered_files:
                    self.filtered_files.remove(file_info)
                
                # 刷新列表
                search_text = self.search_input.text
                self.filter_files(search_text)
                
                self.status_label.text = "文件已成功删除"
                confirm_popup.dismiss()
            except Exception as e:
                self.show_message("错误", f"无法删除文件: {str(e)}")
        
        def on_no(instance):
            confirm_popup.dismiss()
        
        yes_btn.bind(on_press=on_yes)
        no_btn.bind(on_press=on_no)
        
        button_layout.add_widget(yes_btn)
        button_layout.add_widget(no_btn)
        
        layout.add_widget(button_layout)
        
        confirm_popup.content = layout
        confirm_popup.open()

# 定义Kivy组件的kv字符串
KV = '''
<FileItem>:
    orientation: 'vertical'
    padding: 5
    spacing: 2
    canvas.before:
        Color: 
            rgba: 0.7, 0.7, 0.7, 0.5
        Rectangle:
            pos: self.pos
            size: self.size
    Label:
        text: root.name
        size_hint_y: 0.5
        halign: 'left'
        valign: 'middle'
        text_size: self.size
        font_size: '14sp'
    BoxLayout:
        orientation: 'horizontal'
        size_hint_y: 0.5
        Label:
            text: root.ext
            halign: 'left'
            valign: 'middle'
            text_size: self.size
            font_size: '12sp'
        Label:
            text: root.size
            halign: 'center'
            valign: 'middle'
            text_size: self.size
            font_size: '12sp'
        Label:
            text: root.date
            halign: 'right'
            valign: 'middle'
            text_size: self.size
            font_size: '12sp'

<FileActionPopup>:
    file_info: None
    app: None
    BoxLayout:
        orientation: 'vertical'
        padding: 10
        spacing: 10
        Label:
            text: '选择操作'
            font_size: '16sp'
        GridLayout:
            cols: 2
            spacing: 10
            size_hint_y: 0.7
            Button:
                text: '打开文件'
                on_press: app.open_file(root.file_info); root.dismiss()
            Button:
                text: '打开文件位置'
                on_press: app.open_file_location(root.file_info); root.dismiss()
            Button:
                text: '复制文件路径'
                on_press: app.copy_file_path(root.file_info); root.dismiss()
            Button:
                text: '添加/编辑备注'
                on_press: app.add_note(root.file_info); root.dismiss()
            Button:
                text: '复制到自定义文件夹'
                on_press: app.copy_to_custom_folder(root.file_info); root.dismiss()
            Button:
                text: '文件改名'
                on_press: app.rename_file(root.file_info); root.dismiss()
            Button:
                text: '删除文件'
                background_color: 0.7, 0, 0, 1
                on_press: app.delete_file(root.file_info); root.dismiss()
        Button:
            text: '取消'
            on_press: root.dismiss()
'''

# 从kivy.lang导入Builder
from kivy.lang import Builder

# 加载KV定义
Builder.load_string(KV)

# 启动应用
if __name__ == '__main__':
    app = MobileScannerApp().run()